package com.lengyu.vxminiprogram.security.jwt;

import com.alibaba.fastjson.JSONObject;
import com.lengyu.vxminiprogram.common.BaseConstant;
import com.lengyu.vxminiprogram.security.exception.TokenException;
import com.lengyu.vxminiprogram.security.rest.dto.JwtUser;
import io.jsonwebtoken.*;
import io.jsonwebtoken.impl.Base64UrlCodec;
import io.jsonwebtoken.impl.DefaultClaims;

import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import java.util.Date;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class JwtUtils {
    private final Logger log = LoggerFactory.getLogger(JwtUtils.class);
    private static final String SECRET = "EENDTECHHCETDNEE520131....4!@#$%Y^ASDHUIsadasd#@#!@#156489d1svxcv4cx123a894!!@@@@###@{}{}{gasyudgas}JAIOASJD";

    private static final String ISS = "LENGYU";//签发者

    //默认过期时间是1天
    private static final long EXPIRATION = 3600 * 24 * 1000L;
//    private static final long EXPIRATION =  1000L;
    //生成TOKEN
    /***
     * 函数名: GenToken
     * 函数说明: 生成TOKEN令牌
     * 创建时间: 2020/2/7 20:01
     * @Param userName: 用户名
     * @Param group: 当前用户组
     * @Param isForever: 是否为永久令牌
     * @param uid: 用户的id
     * @return: java.lang.String

     */

    public static String GenToken(JwtUser user, String uid, boolean isForever) {

        Claims claims = new DefaultClaims();

        claims.setId(uid)
                .setIssuer(ISS) //签发者
                .setIssuedAt(new Date()) // 签发时间
                .setAudience(user.getUsername()); //接收方
        claims.put("user", JSONObject.toJSONString(user));

//        JwtBuilder jwt = Jwts.builder();
//        jwt.signWith(SignatureAlgorithm.HS512, generalKey());
//        jwt.setId(uid.toString());
//        jwt.setClaims(claims);

      long now = (new Date()).getTime();
      long exp = System.currentTimeMillis() + EXPIRATION;

        String jwtData = Jwts.builder()
//         .setSubject(user.getUsername())
                .setClaims(claims)
                .signWith(generalKey(), SignatureAlgorithm.HS512)
                .setExpiration(new Date(exp))
                .setId(uid)
                .compact();
        System.err.print("当前生成的signKey:" + "\t");
//
//        for (byte i : generalKey().getEncoded()) System.err.print(i);
//
//        if (!isForever) {
//            long exp = System.currentTimeMillis() + EXPIRATION;
//            jwt.setExpiration(new Date(exp)); // 设置过期时间为一天后
//        }
//        String r = jwt.compact();
//        System.out.println("\n原始Token\t" + r);
        // 对结果进行Base64Url编码后发送
        jwtData = Base64UrlCodec.BASE64URL.encode(jwtData);
        return jwtData; //返回生成的令牌
    }

    //从令牌中获取用户名
    public static String getJwtUser(String token) {
        return String.valueOf(validateJwt(token).get("user"));
    }
//
//    //从令牌中获取uid
//    public static String getUid(String token) {
//        return validateJwt(token).getId();
//    }

//    //从令牌中获取用户组
//    public static String getGroup(String token) {
//        return validateJwt(token).get("group").toString();
//    }

    /***
     * 函数名: validateJwt
     * 函数说明: 验证当前的令牌
     * 创建时间: 2020/2/7 20:56
     * @Param token:
     * @return: com.eendtech.witkey.utils.ReturnsKit
     */

    public static Claims validateJwt(String token) {
        Claims claims = null;
        try {
            claims = parseToken(token);
        }catch (ExpiredJwtException e) {
            throw new TokenException(BaseConstant.Returns.TOKEN_PARSE_FAILED,"当前Token过期了");
//            System.err.println("当前Token过期了!");
        }

        catch (SignatureException e1) {
            System.err.println("当前Token检验失败,不符合加密规则");
            throw new TokenException(BaseConstant.Returns.TOKEN_PARSE_FAILED,"当前Token检验失败,不符合加密规则");
        }

        if (claims == null){
            throw new TokenException(BaseConstant.Returns.TOKEN_PARSE_FAILED,"token校验失败");
        }
        return claims;

    }

    // 解析Token playload
    public static Claims parseToken(String token) {
        //对token进行解码
        token = Base64UrlCodec.BASE64URL.decodeToString(token);

        return Jwts.parser()
                .setSigningKey(generalKey())
                .parseClaimsJws(token)
                .getBody();

    }

    public static SecretKey generalKey() {
        byte[] encodeDkey = SECRET.getBytes();
        return new SecretKeySpec(encodeDkey, 0, SECRET.length(), "HmacSHA256");

    }
}
